using System.Drawing;
using SkaldRogueLike.Main.Constants.Enumerations;
using SkaldRogueLike.Main.DungeonGenerating.DirectionProcessing;
using SkaldRogueLike.Main.DungeonGenerating.MapImplementations;

namespace SkaldRogueLike.Main.DungeonGenerating
{
    public static class MapConverter
    {
        public static Tile[,] ConvertDungeonToTiles(Dungeon dungeon)
        {
            var tiles = new Tile[dungeon.Width * 2 + 1, dungeon.Height * 2 + 1];

            for (var x = 0; x < dungeon.Width * 2 + 1; x++)
                for (var y = 0; y < dungeon.Height * 2 + 1; y++)
                    tiles[x, y] = Tile.Wall;

            foreach (var room in dungeon.Rooms)
            {
                var roomMinPoint = new Point(room.Bounds.Location.X * 2 + 1, room.Bounds.Location.Y * 2 + 1);
                var roomMaxPoint = new Point(room.Bounds.Right * 2, room.Bounds.Bottom * 2);

                // Fill tiles with corridor values for each room in dungeon
                for (var i = roomMinPoint.X; i < roomMaxPoint.X; i++)
                    for (var j = roomMinPoint.Y; j < roomMaxPoint.Y; j++)
                        tiles[i, j] = Tile.Empty;
            }

            // Expand it each corridor cell
            foreach (var cellLocation in dungeon.CorridorCellLocations)
            {
                var tileLocation = new Point(cellLocation.X * 2 + 1, cellLocation.Y * 2 + 1);

                tiles[tileLocation.X, tileLocation.Y] = Tile.Empty;
                if(cellLocation == dungeon.DownStairs)
                    tiles[tileLocation.X, tileLocation.Y] = Tile.DownStairs;
                else if(cellLocation == dungeon.UpStairs)
                    tiles[tileLocation.X, tileLocation.Y] = Tile.UpStairs;

                switch (dungeon[cellLocation].GetSide(Dir.North))
                {
                    case Side.Empty:
                        tiles[tileLocation.X, tileLocation.Y - 1] = Tile.Empty;
                        break;
                    case Side.Door:
                        tiles[tileLocation.X, tileLocation.Y - 1] = Tile.Door;
                        break;
                }

                switch (dungeon[cellLocation].GetSide(Dir.South))
                {
                    case Side.Empty:
                        tiles[tileLocation.X, tileLocation.Y + 1] = Tile.Empty;
                        break;
                    case Side.Door:
                        tiles[tileLocation.X, tileLocation.Y + 1] = Tile.Door;
                        break;
                }

                switch (dungeon[cellLocation].GetSide(Dir.West))
                {
                    case Side.Empty:
                        tiles[tileLocation.X - 1, tileLocation.Y] = Tile.Empty;
                        break;
                    case Side.Door:
                        tiles[tileLocation.X - 1, tileLocation.Y] = Tile.Door;
                        break;
                }

                switch (dungeon[cellLocation].GetSide(Dir.East))
                {
                    case Side.Empty:
                        tiles[tileLocation.X + 1, tileLocation.Y] = Tile.Empty;
                        break;
                    case Side.Door:
                        tiles[tileLocation.X + 1, tileLocation.Y] = Tile.Door;
                        break;
                }
            }
            
            return RotateMatrix(tiles);
        }

        private static Tile[,] RotateMatrix(Tile[,] tiles)
        {
            var newWidth = tiles.GetLength(0);
            var newHeight = tiles.GetLength(1);
            var result = new Tile[newHeight, newWidth];
            for (var x = 0; x < newWidth; x++)
                for (var y = 0; y < newHeight; y++)
                    result[newHeight - y - 1, x] = tiles[x, y];
            return result;
        }
    }
}